/*
 * HttpParser.h
 */

#ifndef HTTPPARSER_H_
#define HTTPPARSER_H_

#include <map>
#include <iostream>
#include <iterator>
#include <sstream>
#include "CgiEnvironment.h"
#include "TiposComunes.h"

#define MAX_LONG_QUERY_STRING 255
// Defino la maxima recepción de datos por Post en 128 Kb
#define MAX_LONG_CONTENIDO_POST 131072
#define FIN_NOMBRE_VARIABLE_URL '='
#define FIN_VALOR_VARIABLE_URL '&'
#define TIPO_URLENCODED "application/x-www-form-urlencoded"
#define TIPO_MULTIPART "multipart/form-data"
#define CAMPO_NOMBRE "name"
#define CAMPO_ARCHIVO "filename"
#define FIN_ENCABEZADO "\r\n\r\n"
#define TIPO_CONTENIDO_HTML "text/html"
#define CHARSET_ISO "iso-8859-1"
#define CHARSET_UTF8 "utf-8"

class HttpParser {
private:
	CgiEnvironment cgi;
	std::map<std::string, std::string> varRecibidas;
	std::map<std::string, std::string> varMultipartes;
	typedef std::map<std::string, std::string>::const_iterator tVarRecibIt;

	/** Extrae el valor de una variable encerrado entre comillas.
	 *  @param cadena Cadena donde hace la búsqueda. Formato: variable="valor".
	 *  @param nombre Nombre de la variable buscada
	 *  @param pos Opcional. Posición desde la cual comienza la búsqueda
	 *  @return
	 */
	std::string extraerValorVariable(const std::string &cadena,
			const std::string &nombre, size_t pos = 0) const;

	/**	Lee la entrada standard y la devuelve cargada en un string.
	 * @return Contenido entrada standard.
	 */
	std::string getCin() const;

	/**	Decodifica una cadena codificada en application/x-www-form-urlencoded.
	 * @param cadena Cadena codificada.
	 * @param salida Cadena donde devuelve la entrada decodificada.
	 * @return Falso en caso que no se pueda decodificar
	 */
	bool decodificarUrlencoded(const std::string &cadena,
			std::string &salida) const;

	/**	Extrae las variables de la cadena codificada y las carga internamente.
	 * @param entrada Cadena codificada.
	 * @return Código de respuesta Http.
	 */
	std::string procesarUrlEncoded(const std::string &entrada);

	/**	Extrae las variables del formulario multipart y las carga internamente.
	 * @param boundary Separador de partes de formularios multipart/form-data.
	 * @return Código de respuesta Http.
	 */
	std::string procesarMultipart(const std::string &boundary);

	/** Recibe y parsea los datos según estandard GET
	 * @return Código de respuesta Http
	 */
	std::string procesarMetodoGet();

	/** Recibe y parsea los datos según estandard POST
	 * @return Código de respuesta Http
	 */
	std::string procesarMetodoPost();

public:
	HttpParser() {}
	virtual ~HttpParser() {}

	/** Recibe y parsea los datos según parámetros CGI
	 * @return Código de respuesta HTTP con el resultado
	 */
	std::string recibirMsjHttp();

	/** Busca el valor de la variable en los datos recibidos
	 * @return El valor de la variable si la encuentra o cadena vacia
	 */
	std::string getValorVariable(const std::string &variable) const;

	/** Busca entre los archivos recibidos por su identificación "name"
	 * @return El contenido de archivo o cadena vacia
	 */
	std::string getArchivo(const std::string &nombVar) const;

	/** Analiza la validez de un código de respuesta HTTP
	 * @return Devuelve la validez del status HTTP
	 */
	bool getValidezStatusHttp(const std::string &status) const;

	/** Emite un ecabezado de respuesta segun standard http-cgi.
	 * @param os Stream de salida donde se emitira el encabezado.
	 * @param tipo Tipo de contenido del body http.
	 * @param charset Tipo de codificacion de caracteres del body.
	 * @param status Codigo de respuesta http.
	 * @param location Direccion física de una página estática para redirección
	 */
	void emitirEncabezadoRtaHttpCgi(std::ostream &os,
			const std::string &tipo, const std::string &charset,
			const std::string &status = "",
			const std::string &location = "") const;
};

#endif /* HTTPPARSER_H_ */
